/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package th.stripes.resources;

import com.google.inject.Inject;
import com.oas.thit._this.xsd.THISBaseDataElementBody;
import com.oas.thit.xmlmessage.xsd.Header;
import java.io.BufferedReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.http.HttpSession;
import javax.xml.bind.JAXBElement;
import net.sourceforge.stripes.action.ErrorResolution;
import net.sourceforge.stripes.action.HandlesEvent;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.StreamingResolution;
import net.sourceforge.stripes.action.UrlBinding;
import org.apache.log4j.Logger;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import th.manager.AkaunManager;
import th.manager.ResponseManager;
import th.manager.UserManager;
import th.model.InfoAudit;
import th.model.Pengguna;
import th.service.session.LoginSession;
import th.service.session.SessionManager;
import th.stripes.BaseActionBean;
import th.stripes.webservice.WebServiceUtil;

/**
 *
 * @author fikri
 */
@UrlBinding("/services/login")
public class LoginResource extends BaseActionBean {

    private String userLogin;
    private String userPassword;
    
    
    private final static String VAL_ACC_MSG_ID = "TPUSRMGTWD03";
    private final static String HEADER_ID_VAL_ACCOUNT = "THSACVL";
    private final static String SUCCESSFUL="0000";
    private final static String SYSTEM_ERROR = "9999";
    private final static String INVALID_ACC_STATUS = "5678";
    private final static String STATUS_MATI = "M";
    private final static String STATUS_BATAL = "Z";
    private final static String ACC_STS_TIDAKSAH = "9000";
    private final static String ACC_STS_BANKRUP = "9201";
    private final static String ACC_STS_DORMAN = "9202";
    private final static String ACC_STS_MATI = "9203";
    private final static String ACC_STS_SULIT = "9204";
    private final static String ACC_STS_TUTUP = "9205"; 
    private final static String ACC_STS_EPF = "9206";

    @Inject
    AkaunManager akaunManager;
    @Inject private ResponseManager responseManager;
    @Inject private WebServiceUtil webUtil;  
    @Inject UserManager userManager;
    
    private final com.oas.thit._this.services.THISServices service = new com.oas.thit._this.services.THISServices();
    private final com.oas.thit._this.services.THISServicesPortType port = service.getTHISServicesHttpSoap11Endpoint();
    
    private static Logger LOG = Logger.getLogger(LoginResource.class);
    
    private String ERROR_MSG = "";
    
    private String sessionId = "";

    @HandlesEvent("user_login")
    public Resolution login() {

        String line = null;
        StringBuilder sb = new StringBuilder();
        BufferedReader reader = null;

        try {

            reader = getContext().getRequest().getReader();
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }

            if (sb.length() > 0) {
                JSONParser jsonParser = new JSONParser();
                JSONObject jsonObject = (JSONObject) jsonParser.parse(sb.toString());
                if (jsonObject != null) {
                    userLogin = (String) jsonObject.get("userId");
                    userPassword = (String) jsonObject.get("password");
                }
                
                if (!validation()) {
//                    return new ErrorResolution(401, ERROR_MSG);
                    return new StreamingResolution("text/plain", ERROR_MSG);
                } else {
                    
                    Pengguna pengguna = userManager.findUserByIdUser(getUserLogin(),"Y");       
                    getContext().setCurrentUser(pengguna);   
            //        pengguna.setTarikhAkhirLogin(new Date());
                    pengguna.setBilanganCubaan(0); //set default balik
                    userManager.updatePengguna(pengguna);  
                    
                    return new StreamingResolution("application/json", toJson(pengguna));
                }
                
            }

            
        } catch (IOException ex) {
        } catch (ParseException ex) {
        } finally {
            try {
                if (reader != null) reader.close();
            } catch (IOException ex) {
            }
        }

        return new ErrorResolution(401, ERROR_MSG);
    }
    
    
    public boolean validation() {         
        
        Pengguna pguna = userManager.findUserByIdUser(getUserLogin(),"N");        
        if (pguna != null) {
            
            if(pguna.getBilanganCubaan()>=3){
                ERROR_MSG = "Akaun anda telah disekat. Sila tukar kata laluan.";
                return false;
            } else {
                 ERROR_MSG = "Akaun tidak aktif. Sila tukar kata laluan.";
                 return false;
            }
            
        } else if (!userManager.authenticate(getUserLogin(), getUserPassword())) {
            ERROR_MSG = "ID Pengguna / Kata Laluan salah.";
            Pengguna pengguna = userManager.findUserByIdUser(getUserLogin(),"Y");
            
            if (pengguna != null) {
                int cubaan = (pengguna.getBilanganCubaan()== null?0:pengguna.getBilanganCubaan())+1;
                if (cubaan > 2) {
                    pengguna.setActive('N');       
                    ERROR_MSG = "Akaun anda telah disekat. Sila tukar kata laluan.";
                }
                else {
                    
                    int i = 3-cubaan;
                    
                    StringBuilder error = new StringBuilder("ID Pengguna / Kata Laluan salah. ")
                            .append("Anda mempunyai ")
                            .append(String.valueOf(i))
                            .append(" kali cubaan sahaja lagi");
                    
                    
                    ERROR_MSG = error.toString();
                }
                 pengguna.setBilanganCubaan(cubaan);
                 userManager.updatePengguna(pengguna);
            }
            return false;
        } else {
            
            pguna = userManager.findUserByIdUser(getUserLogin(),"Y");
            if(pguna == null){
                ERROR_MSG = "Pengguna tidak wujud.";
                return false;
            }
            
            //validate user availability
            if (pguna.getJenisPengguna().getKod().equals("001")) { 
               String responseCode = "";
                try { // Call Web Service Operation
                    // TODO initialize WS operation arguments here
                    com.oas.thit._this.xsd.THISRequest req = new com.oas.thit._this.xsd.THISRequest();
                    // TODO process result here                
                    com.oas.thit._this.xsd.ObjectFactory objFactory = new com.oas.thit._this.xsd.ObjectFactory();
                    req.setHeader(webUtil.createHeader(VAL_ACC_MSG_ID, HEADER_ID_VAL_ACCOUNT));
                    THISBaseDataElementBody reqBody = objFactory.createTHISBaseDataElementBody();


                    String noAkaun = akaunManager.getNoAkaun(pguna.getNoKp(), "Y");

                    reqBody.setTHAcct(objFactory.createTHISBaseDataElementBodyTHAcct(noAkaun));
                    reqBody.setTHICNo(objFactory.createTHISBaseDataElementBodyTHICNo(pguna.getNoKp()));

                    JAXBElement<THISBaseDataElementBody> jReqBody = objFactory.createTHISRequestBody(reqBody);
                    req.setBody(jReqBody);

                    com.oas.thit._this.pin.xsd.AccountValidationResponse result = port.validateAccount(req);

                    Header header = result.getHeader().getValue();
                    responseCode = header.getResponseCode().getValue();
                    if (!responseCode.equals(SUCCESSFUL) 
                            && !responseCode.equals(ACC_STS_SULIT) 
                            && !responseCode.equals(ACC_STS_BANKRUP) 
                            && !responseCode.equals(ACC_STS_DORMAN) 
                            && !responseCode.equals(ACC_STS_EPF)) {
//                    AccountValidationResponseBody resp = result.getBody().getValue();
//                    if(resp.getTHAcctStatus()!=null && (resp.getTHAcctStatus().getValue().trim().equals(STATUS_MATI) || resp.getTHAcctStatus().getValue().trim().equals(STATUS_BATAL))){
//                        addSimpleError("" + responseManager.getResponseMessage(INVALID_ACC_STATUS ,VAL_ACC_MSG_ID));
                        ERROR_MSG = responseManager.getResponseMessage(ACC_STS_TIDAKSAH, VAL_ACC_MSG_ID);
                        return false;
//                    }
                    }
                } catch (Exception ex) {
                    LOG.error(ex);
                    responseCode = SYSTEM_ERROR;
                    ERROR_MSG = responseManager.getResponseMessage(responseCode, VAL_ACC_MSG_ID);
                    return false;
                }
            }
            
            
            SessionManager sm = SessionManager.getInstance();
            LoginSession ls = sm.getActiveSessionByUserId(getUserLogin());
             if (ls != null) {
                 ERROR_MSG = "Pengguna \"" + getUserLogin() + "\" "
                            + "telah pun log masuk pada " + formatSDF(ls.getDateCreated()) + ". Sila klik Log Keluar untuk keluar "
                            + "dari sistem terlebih dahulu";
                 return false;
             }
             
            HttpSession ses = context.getRequest().getSession();
            ses.setAttribute(th.stripes.config.ableActionBeanContext.USER_ID_KEY, getUserLogin());
            
            sessionId = ses.getId();

            sm.addSession(sessionId, getUserLogin(), new Date(),
                    context.getRequest().getRemoteAddr(), context.getRequest().getRemoteHost());
            
            InfoAudit ia = new InfoAudit();
            ia.setDimasukOleh(pguna);
            ia.setTarikhMasuk(new Date());
            pguna.setBilanganCubaan(new Integer(0));
            userManager.updatePengguna(pguna);
            context.getServletContext().setAttribute("save_count", new Integer(0));
            
            return true;
        }        
    }
    

    private String toJson(Pengguna pengguna) {

        String noAkaun = akaunManager.getNoAkaun(pengguna.getNoKp(), "Y");

        JSONObject obj = new JSONObject();
        obj.put("userId", pengguna.getIdPengguna());
        obj.put("noKp", pengguna.getNoKp());
        obj.put("noAkaun", noAkaun);
        obj.put("sessId", sessionId);

        return obj.toJSONString();
    }
    
    public String getUserLogin() {
        return userLogin;
    }
    
    public String getUserPassword() {
        return userPassword;
    }
    
    private String formatSDF(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        return sdf.format(date);
    }

}
